package com.example.kotlindemo

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.joe.mvvm.activity.MvvmDemoActivity
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.*

/**
 * A simple [Fragment] subclass as the default destination in the navigation.
 */
class FirstFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.button_next).setOnClickListener {
            // 测试切换下一个TAB
            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
        }
        view.findViewById<Button>(R.id.button_first).setOnClickListener {
            testDemo()
        }
        view.findViewById<Button>(R.id.button_loop).setOnClickListener {
            // 测试循环
            testLoop()
        }
        view.findViewById<Button>(R.id.button_class).setOnClickListener {
            // 测试类
            testClass()
        }
        view.findViewById<Button>(R.id.button_null).setOnClickListener {
            // 测试空值
            testNullValue()
        }
        view.findViewById<Button>(R.id.button_collection).setOnClickListener {
            // 测试集合
            testCollection()
        }
        view.findViewById<Button>(R.id.button_mvvm).setOnClickListener {
            // 测试MVVM
            testMvvmDemo()
        }
    }

    /**
     * 测试跳转MVVM
     *
     */
    private fun testMvvmDemo() {
        startActivity(Intent(activity, MvvmDemoActivity::class.java))
    }

    /**
     * 测试集合
     */
    private fun testCollection() {
        // 测试只读列表
        println("===测试只读列表===")
        var readList = listOf("aaa", "bbb", "cccc")
        // 允许读取集合中元素
        println("${readList[0]}")
        // 测试可变集合
        var writeList = mutableListOf(1, 2, 3, 4, 5, 6)
        println("${writeList[0]}")
//        writeList[0] = 125
        println("改变后的值${writeList[0]}")
        // 测试序列
        val result = writeList.filter {
            println("filter $it")
            it > 2
        }.map {
            // 进行变换，原来的值进行映射变化后，返回新的值
            println("map $it")
            it * 2
        }.toList()
        // 打印变换后的结果
        println("===测试序列结果===")
        for (it in result) {
            println("$it")
        }
    }

    /**
     * 测试空值处理
     */
    private fun testNullValue() {
        // 声明变量name是可以为空的变量
        var name: String? = null
        // 判断参数name是否为空，不为空则打印name的长度，为空则输出0
        println(name?.length ?: 0)
        // 类型转换
        var obj: Any? = "abc"
        if (obj is String) {
            // 会智能转化为对应类型的实例
            println("obj is String length: " + obj.length)
        }
        // 强制转换
        println("===测试强制转换===")
        // 如果转换成功则转化为String，转换失败则为null
        val str = obj as? Int
        // str为非空字符串则打印str长度，否则打印null
        println(str?.toChar())
        // 非空断言(str为空则抛出空指针)
//        println(str!!.length)
        // 测试数组类型
        println("===测试intArrayOf数组===")
        var array1 = intArrayOf(1, 2, 5)
        for (it in array1) {
            println("$it")
        }
        println("===测试arrayOf数组===")
        var array2 = arrayOf("1", 2, 5)
        for (it in array2) {
            println("$it")
        }
        add(1)
    }

    /**
     * 限定参数只能接收 Number 的子类
     */
    fun <E : Number> add(e: E) {}

    /**
     * 泛型类
     */
    class TestGen<E> {

        /**
         * 对应元素
         */
        var elment: E? = null

        /**
         * 定义泛型方法，输入参数e，输出参数为泛型E类型
         */
        fun <E> add(e: E) {
        }
    }

    /**
     * 数据类
     */
    data class User(var name: String, val gender: String) {

        /**
         * 注册时间
         */
        var registerTime: String = ""

    }

    /**
     * 测试类
     */
    private fun testClass() {
        // 测试类
        var person = Person("小小猫", 25)
        println("Person 姓名: ${person.name} 年龄：${person.age}")
        println("Pserson info: ${person.toString()}")
        // 测试数据类
        var jakson = User(name = "jakson", gender = "男")
        // 更新注册时间
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            val date = LocalDate.now()
            val fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd")
            val dateStr = date.format(fmt)
            println("dateStr $dateStr")
            jakson.registerTime = dateStr
        }
        // 数据类自动实现toString（）。com.example.coroutines.User(name=jakson, gender=男)
        println("jakson info: ${jakson.toString()}")
        // 测试数据类拷贝
        println("===测试数据类拷贝===")
        var peter = jakson.copy(name = "peter")
        println("peter info: ${peter} registerTime：${peter.registerTime}")
        // 数据类解构声明(按照主构造函数进行变量赋值)
        println("===测试数据类解构声明===")
        val (nameStr, iAge) = jakson
        println("$nameStr, $iAge years of age") // prints "Jane, 35 years of age"
        // 测试枚举类
        testEnumClass()
        // 测试密闭类
        testSealedClass()
        // 测试对象
        testObject()
    }

    /**
     * 直接声明对象
     */
    object XBus {

        /**
         * 颜色
         */
        var color: String = "绿色"

        /**
         * 座位
         */
        var seat: Int = 30
    }

    // 私有函数，所以其返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函数，所以其返回类型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    /**
     * 测试对象
     */
    private fun testObject() {
        println("===测试object对象===")
        // object声明的对象相当于一个单例
        println("XBus 颜色：${XBus.color} 座位: ${XBus.seat} 个")
        // 指向同一个单例对象结果相等
        var obj1 = XBus
        obj1.color = "红色"
        var obj2 = XBus
        println("${obj1 == obj2}")
        // XBus 颜色：红色 座位: 30 个
        println("XBus 颜色：${obj2.color} 座位: ${obj2.seat} 个")
        // 测试object匿名对象
        println("${foo().x}")
    }

    /**
     * 测试枚举类
     */
    private fun testEnumClass() {
        // 测试枚举类
        println("===测试枚举类===")
        var shape = Shape.CIRCLE
        // 图形 CIRCLE ordinal 1
        println("图形 ${shape.name} ordinal ${shape.ordinal}")
        // 根据枚举类名称获取枚举类
        shape = Shape.valueOf("OVAL")
        // 打印枚举类名称(OVAL)
        println("获取的枚举类型对象为 ${shape.name}  ordinal ${shape.ordinal}")
//        // 枚举类名没有匹配上的话则会抛出异常
//        shape = Shape.valueOf("BOX")
//        println("获取的枚举类型对象为 ${shape.name}")
        // 打印枚举类的描述(椭圆)
        println("图形 ${shape.desc}")
        // 枚举类常量遍历
        println("===枚举类常量遍历===")
        var items: Array<Shape> = enumValues<Shape>()
        for (item: Shape in items) {
            println("枚举元素 ${item.name}")
        }
        // 通过枚举名称查找枚举类常量
        println("===查找枚举类===")
        var child: Shape = enumValueOf("RECTANGLE")
        println("枚举元素 ${child.name}")
    }

    /**
     * 测试密封类
     */
    private fun testSealedClass() {
        println("===测试密闭类===")
        var man = Gender.Man()
        println("密闭类 ${man.type}")
        // 打印性别
        printGender(man)
    }

    /**
     * 打印性别
     */
    private fun printGender(gender: Gender) {
        // 密闭类判读的时候只需要枚举子类情形，不必要处理else
        when (gender) {
            is Gender.Man -> println("是个男人")
            is Gender.Woman -> println("是个女人")
        }
    }

    inline fun <reified T : Enum<T>> printAllValues() {
        print(enumValues<T>().joinToString { it.name })
    }

    /**
     * 测试循环
     */
    private fun testLoop() {
        val items = listOf("大毛", "二毛", "明明")
        for (item in items) {
            println(item)
        }
        // 根据索引循环遍历
        for (index in items.indices) {
            // items[index]按照索引获取元素值，或者使用items.get(index)
            println("item $index is ${items[index]}")
        }
        // 测试forEach
        println("===测试forEach===")
        items.forEach {
            println(it)
        }
        // 带下标和元素遍历
        println("===测试for...withIndex===")
        for ((index, value) in items.withIndex()) {
            println("$index is $value")
        }
        println("使用迭代器循环遍历")
        // 使用迭代器循环遍历
        var it = items.iterator()
        while (it.hasNext()) {
            println("item ${it.next()}")
        }
        // 测试do...while循环
        println("===测试do...while循环===")
        var i = 0
        do {
            println("第 ${i + 1} 次循环 i=$i")
            i ++
        } while (i < 5)
        // 测试continue和break
        println("===测试continue和break===")
        loop@ for (i in 1 .. 3) {
            var j = 10
            while (true) {
                if (j == 5) {
                    println("j == 5 continue")
                    j --
                    continue
                } else if (j < 0) {
                    println("j < 0 break")
                    break@loop
                } else {
                    j --
                    println("当前j的值: $j")
                }
            }
        }
        println("===测试循环结束===")
    }

    /**
     * Demo测试
     */
    private fun testDemo() {
        printSum(4, 5)
        // 测试Map
        testMap()
        // 测试条件
        testCondition();
    }

    /**
     * 测试条件表达式
     */
    private fun testCondition() {
        var a = 5
        // 测试IF表达式
        if (a > 60) {
            println("我及格了")
        } else {
            println("真糟糕，我没及格")
        }
        // 测试WHEN表达式
        var x = 88
        when (x) {
            in 0 until 60 -> println("还是没及格，加油呀")
            in 60 until 80 -> println("及格了")
            in 80 until 90 -> println("良好，还可以")
            in 90 .. 100 -> println("你真优秀")
            else -> println("无效分数")
        }
    }

    /**
     * 测试Map
     */
    private fun testMap() {
        var map = TreeMap<String, String>()
        map["姓名"] = "大头儿子"
        map["性别"] = "男"
        map["年龄"] = "9岁"
        // 打印一个键值对
        println(map["性别"])
        // 属性遍历
        for ((i, e) in map) {
            println("$i --> $e")
        }
    }


    private fun printSum(a: Int, b: Int): Unit {
        println(a + b)
    }

    public fun sum(a: Int, b: Int): Int {
        return a + b;
    }
}